package com.vvvtimes.demo.util.endecrypt;

import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.BufferedBlockCipher;
import org.bouncycastle.crypto.InvalidCipherTextException;
import org.bouncycastle.crypto.engines.DESEngine;
import org.bouncycastle.crypto.modes.CBCBlockCipher;
import org.bouncycastle.crypto.paddings.PKCS7Padding;
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher;
import org.bouncycastle.crypto.params.DESParameters;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;

public class BcDesEngineUtil {

    private final static BlockCipher engine;
    private static final BouncyCastleProvider provider;

    /**
     * 偏移变量，固定占8位字节
     */
    private final static String IV_PARAMETER = "12345678";

    /**
     * 生成key
     *
     * @param password 密钥字符串
     * @return 密钥对象
     * @throws Exception
     */
    private static byte[] convertKeyEncoded(byte[] password) {
        byte[] result = null;
        try {
            DESKeySpec dks  = new DESKeySpec(password);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES",provider);
            SecretKey secretKey = keyFactory.generateSecret(dks);
            return secretKey.getEncoded();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }
        return result;

    }

    private static byte[] encrypt( byte[] ptBytes,byte[] key) throws InvalidCipherTextException, UnsupportedEncodingException {
        BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(engine), new PKCS7Padding());
        cipher.init(true, new ParametersWithIV(new DESParameters(key), IV_PARAMETER.getBytes("utf-8")));
        byte[] rv = new byte[cipher.getOutputSize(ptBytes.length)];
        int tam = cipher.processBytes(ptBytes, 0, ptBytes.length, rv, 0);

        cipher.doFinal(rv, tam);
        return rv;
    }


    private static byte[] decrypt( byte[] cipherText,byte[] key) throws InvalidCipherTextException, UnsupportedEncodingException {
        BufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new CBCBlockCipher(engine), new PKCS7Padding());
        cipher.init(false, new ParametersWithIV(new DESParameters( key),IV_PARAMETER.getBytes("utf-8")));
        byte[] rv = new byte[cipher.getOutputSize(cipherText.length)];
        int tam = cipher.processBytes(cipherText, 0, cipherText.length, rv, 0);
        cipher.doFinal(rv, tam);
        return rv;
    }

    /**
     * byte数组转十六进制
     *
     * @param bytes
     * @return
     */
    public static String byte2HexString(byte[] bytes) {
        StringBuilder hex = new StringBuilder();
        if (bytes != null) {
            for (Byte b : bytes) {
                hex.append(String.format("%02X", b.intValue() & 0xFF));
            }
        }
        return hex.toString();
    }

    //测试
    public static void main(String[] args) throws Exception {
        String source = "admin测试信息1234!@#$%^&*()_+";
        System.out.println("原  文: " + source);
        String password = "lw112190@2023";
        //String password ="geffzhan";
        //String password ="lw112190";
        byte[] keyEncoded = convertKeyEncoded(password.getBytes("utf-8"));

        byte[] encryptDataBytes = encrypt(source.getBytes("utf-8"), keyEncoded);
        String encryptData = byte2HexString(encryptDataBytes);
        System.out.println("加密后: " + encryptData);
        byte[] decryptDataBytes = decrypt(encryptDataBytes, keyEncoded);
        String decryptData = new String(decryptDataBytes, "utf-8");
        ;
        System.out.println("解密后: " + decryptData);
        /*
         *原  文: admin测试信息1234!@#$%^&*()_+
        加密后: 1D5C21B694A9085A69BE7EA37C197D1632239545298613B944C3AC272750A519F66FB43EFEC55C89
        解密后: admin测试信息1234!@#$%^&*()_+
         */
    }

    static {
        engine = new DESEngine();
        provider = new BouncyCastleProvider();
    }

}
